<template>
  <el-form
      ref="formRef"
      :model="formData"
      :rules="rules"
      label-width="120px"
      class="custom-form"
  >
    <el-row :gutter="20">
      <el-col
          v-for="(item, index) in columns"
          :key="index"
          :span="item.span || 12"
          class="form-item-col"
      >
        <el-form-item
            :label="item.label"
            :prop="item.prop"
            :required="item.required"
            :rules="item.rules"
        >
          <component
              :is="getComponent(item.type)"
              v-model="formData[item.prop]"
              v-bind="item.props"
              :placeholder="item.placeholder || `请输入${item.label}`"
          >
            <template v-if="item.options && item.type === 'select'">
              <el-option
                  v-for="opt in item.options"
                  :key="opt.value"
                  :label="opt.label"
                  :value="opt.value"
              />
            </template>
          </component>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script setup lang="ts">
import { defineProps, defineEmits, ref, watch, ComputedRef, computed } from 'vue';
import {
  ElInput,
  ElSelect,
  ElCheckbox,
  ElRadio,
  ElDatePicker,
  ElTimePicker,
  ElInputNumber,
  ElSwitch,
  ElForm,
  ElFormItem,
  ElCol,
  ElRow,
  ElOption
} from 'element-plus';

// 定义表单项目类型
type FormItemType = 'input' | 'select' | 'checkbox' | 'radio' | 'date-picker' | 'time-picker' | 'input-number' | 'switch';

// 定义单个表单项的配置接口
interface FormColumn {
  prop: string;               // 字段名，对应formData中的属性
  label: string;              // 标签文本
  type: FormItemType;         // 表单组件类型
  span?: number;              // 占的栅格数，默认12
  required?: boolean;         // 是否必填
  rules?: any[];              // 验证规则
  placeholder?: string;       // 占位文本
  props?: Record<string, any>; // 组件的其他属性
  options?: { label: string; value: any }[]; // 选择类组件的选项
}

// 定义表单数据类型
type FormData = Record<string, any>;

// 入参定义
const props = defineProps<{
  columns: FormColumn[];  // 表单列配置
  formData: FormData;     // 表单数据对象
}>();

// 出参事件定义
const emit = defineEmits<{
  (e: 'set-columns', columns: FormColumn[]): void;  // 设置columns的方法
  (e: 'set-form-data', formData: FormData): void;    // 设置formData的方法
}>();

// 表单引用
const formRef = ref<InstanceType<typeof ElForm> | null>(null);

// 计算属性：根据columns生成验证规则
const rules = computed(() => {
  const formRules: Record<string, any[]> = {};

  props.columns.forEach(column => {
    if (column.required && !column.rules) {
      formRules[column.prop] = [{
        required: true,
        message: `${column.label}不能为空`,
        trigger: 'blur'
      }];
    } else if (column.rules) {
      formRules[column.prop] = column.rules;
    }
  });

  return formRules;
});

// 根据类型获取对应的组件
const getComponent = (type: FormItemType): ComputedRef<any> => {
  return computed(() => {
    switch (type) {
      case 'input':
        return ElInput;
      case 'select':
        return ElSelect;
      case 'checkbox':
        return ElCheckbox;
      case 'radio':
        return ElRadio;
      case 'date-picker':
        return ElDatePicker;
      case 'time-picker':
        return ElTimePicker;
      case 'input-number':
        return ElInputNumber;
      case 'switch':
        return ElSwitch;
      default:
        return ElInput;
    }
  });
};

// 暴露给父组件的方法：设置columns
const setColumns = (columns: FormColumn[]) => {
  emit('set-columns', columns);
};

// 暴露给父组件的方法：设置formData
const setFormData = (formData: FormData) => {
  emit('set-form-data', formData);
};

// 获取当前表单数据
const getFormData = (): FormData => {
  return { ...props.formData };
};

// 新增：表单校验相关方法
/**
 * 验证整个表单
 * @returns 校验是否通过
 */
const validate = async (): Promise<boolean> => {
  if (!formRef.value) return false;
  try {
    await formRef.value.validate();
    return true;
  } catch (error) {
    return false;
  }
};

/**
 * 验证表单的部分字段
 * @param props 需要验证的字段
 * @returns 校验是否通过
 */
const validateField = async (props: string | string[]): Promise<boolean> => {
  if (!formRef.value) return false;
  try {
    await new Promise((resolve, reject) => {
      formRef.value!.validateField(props, (error) => {
        if (error) {
          reject(error);
        } else {
          resolve(true);
        }
      });
    });
    return true;
  } catch (error) {
    return false;
  }
};

/**
 * 清除表单的验证状态
 */
const clearValidate = (props?: string | string[]) => {
  formRef.value?.clearValidate(props);
};

// 监听formData变化
watch(
    () => props.formData,
    (newVal) => {
      // 数据同步逻辑
    },
    { deep: true }
);

// 监听columns变化
watch(
    () => props.columns,
    (newVal) => {
      // 配置同步逻辑
    },
    { deep: true }
);

// 暴露组件方法
defineExpose({
  setColumns,
  setFormData,
  getFormData,
  validate,       // 新增：验证整个表单
  validateField,  // 新增：验证部分字段
  clearValidate   // 新增：清除验证状态
});
</script>

<style scoped>
.custom-form {
  width: 100%;
  padding: 20px;
  box-sizing: border-box;
  background-color: #fff;
  border-radius: 4px;
}

.form-item-col {
  margin-bottom: 16px;
}
</style>
